/*
@Time : 2020/4/28 0028 15:24
@Author : visons
上传文件到微信服务器
微信文档地址：https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/customer-message/customerServiceMessage.uploadTempMedia.html
*/
package message

import (
	"bytes"
	"encoding/json"
	"fmt"
	"gitee.com/visons/gopkg/logger"
	"gitee.com/visons/gopkg/weixin/platform"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"os"
)

const UpLoadURL = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s"

type UploadMedia struct {
	Type  string `json:"type"`
	Media *Media `json:"media"`
}

type Media struct {
	Value       *bytes.Buffer `json:"value"`
	ContentType string        `json:"contentType"`
}

type UploadRes struct {
	ErrMsg    string `json:"errMsg"`
	ErrCode   int64  `json:"errCode"`
	Type      string `json:"type"`       //文件类型
	MediaId   string `json:"media_id"`   //媒体文件上传后，获取标识，3天内有效
	CreatedAt int64  `json:"created_at"` //媒体文件上传时间戳
}

func UploadTempMedia(appId, secret, Type, uploadImagePath string) (*UploadRes, error) {
	accessToken, err := platform.GetAccessToken(appId, secret)
	if err != nil {
		logger.Error("get accessToken error:%v", err)
		return nil, err
	}
	reqUrl := fmt.Sprintf(UpLoadURL, accessToken.AccessToken, Type)
	logger.Info("upload media request url:", reqUrl)

	res, err := postFile(uploadImagePath, reqUrl)
	if err != nil {
		logger.Error("upload media err:%v", err)
		return nil, err
	}
	uploadRes := &UploadRes{}
	err = json.Unmarshal(res, uploadRes)
	if err != nil {
		logger.Error("unmarshal upload media response err:%v", err)
		return nil, err
	}
	return uploadRes, nil
}

func postFile(filename string, targetUrl string) ([]byte, error) {
	bodyBuf := &bytes.Buffer{}
	bodyWriter := multipart.NewWriter(bodyBuf)

	//关键的一步操作
	fileWriter, err := bodyWriter.CreateFormFile("media", filename)
	if err != nil {
		//.Println("error writing to buffer")
		return nil, err
	}

	//打开文件句柄操作
	fh, err := os.Open(filename)
	if err != nil {
		//fmt.Println("error opening file")
		return nil, err
	}
	defer fh.Close()

	//iocopy
	_, err = io.Copy(fileWriter, fh)
	if err != nil {
		return nil, err
	}

	contentType := bodyWriter.FormDataContentType()
	bodyWriter.Close()

	resp, err := http.Post(targetUrl, contentType, bodyBuf)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	//logger.Info("post file response:%s", string(respBody))
	return respBody, nil
}
